package com.stock.stockprediction.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stock.stockprediction.entity.Stock;
import com.stock.stockprediction.entity.StockMongo;
import com.stock.stockprediction.entity.vo.StockMonthVo;
import com.stock.stockprediction.entity.vo.StockVo;
import com.stock.stockprediction.mapper.StockMapper;
import com.stock.stockprediction.service.StockService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xtt
 * @since 2022-06-03
 */
@Slf4j
@Service
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements StockService {

    @Autowired
    private MongoTemplate mongoTemplate;

    //返回分页所有数据
    @Override
    @Cacheable(value = "dailyDataByPage",keyGenerator = "keyGenerator")
    public Map<String, Object> getStockList(Page<Stock> stockPage, StockVo stock) {
        QueryWrapper<Stock> wrapper=new QueryWrapper<Stock>();
        if(!StringUtils.isEmpty(stock.getStartTime())&&!StringUtils.isEmpty(stock.getEndTime())){
            wrapper.ge("date",new SimpleDateFormat("yyyy-MM-dd").format(stock.getStartTime()))
                    .le("date",new SimpleDateFormat("yyyy-MM-dd").format(stock.getEndTime()));
        }
        if(!StringUtils.isEmpty(stock.getCode())){
            wrapper.eq("code",stock.getCode());
        }

        baseMapper.selectPage(stockPage, wrapper);
        List<Stock> records = stockPage.getRecords();


        long current = stockPage.getCurrent();                //当前页
        long pages = stockPage.getPages();                    //总页数
        long size = stockPage.getSize();                      //每页记录数
        long total = stockPage.getTotal();                    //总记录数
        boolean hasNext = stockPage.hasNext();                //下一页
        boolean hasPrevious = stockPage.hasPrevious();        //上一页


        //把分页数据获取出来，放到map集合中
        Map<String,Object> map=new HashMap<>();
        map.put("items", records);
        map.put("current", current);
        map.put("pages", pages);
        map.put("size", size);
        map.put("total", total);
        map.put("hasNext", hasNext);
        map.put("hasPrevious", hasPrevious);
        //map返回
        return map;
    }
    //查询所有月数据
    @Override
    @Cacheable(value = "monthData",keyGenerator = "keyGenerator")
    public Map<String, Object> getStockListByMonth(StockVo stockVo) {
        Map<String,Object> map=new HashMap<>();
        List<StockMonthVo> list = baseMapper.getStockListByMonth(stockVo);
        List<String> date = list.stream().map(x -> {
            return x.getDate();
        }).collect(Collectors.toList());
        List<BigDecimal> open = list.stream().map(x -> {
            return x.getOpen();
        }).collect(Collectors.toList());
        List<BigDecimal> close = list.stream().map(x -> {
            return x.getClose();
        }).collect(Collectors.toList());
        //月最高价
        List<BigDecimal> high = list.stream().map(x -> {
            return x.getHigh();
        }).collect(Collectors.toList());
        //月最低价
        List<BigDecimal> low = list.stream().map(x -> {
            return x.getLow();
        }).collect(Collectors.toList());
        //月成交量
        List<Long> volume = list.stream().map(x -> {
            return x.getVolume();
        }).collect(Collectors.toList());

        //将所有指标进行封装
        map.put("list",list);
        map.put("date",date);
        map.put("open",open);
        map.put("close",close);
        map.put("high",high);
        map.put("low",low);
        map.put("volume",volume);
        return map;
    }

    //查询所有月数据(带分页)
    @Override
    @Cacheable(value = "monthDataByPage",keyGenerator = "keyGenerator")
    public Map<String,Object> getAllMonthData(Long page, Long limit) {
        Map<String,Object> map = new HashMap<>();
        Integer count=baseMapper.countAllMonthData();
        Long firstLimitParam=(page-1)*limit;

        List<StockMonthVo> list = baseMapper.getAllMonthData(firstLimitParam,limit);

        map.put("list",list);
        map.put("count",count);
        return map;
    }

    //获取所有股票日数据并对结果进行封装
    @Override
    @Cacheable(value = "dailyData",keyGenerator = "keyGenerator")
    public Map<String, Object> getAllDialyData(StockVo stockVo) {
        Map<String,Object> map = new HashMap<>();
        //封装条件
        QueryWrapper<Stock> wrapper = new QueryWrapper<>();
        if(!StringUtils.isEmpty(stockVo.getCode())){
            wrapper.eq("code",stockVo.getCode());
        }
        if(!StringUtils.isEmpty(stockVo.getStartTime())&&!StringUtils.isEmpty(stockVo.getEndTime())){
            wrapper.ge("date",new SimpleDateFormat("yyyy-MM-dd").format(stockVo.getStartTime()))
                    .le("date",new SimpleDateFormat("yyyy-MM-dd").format(stockVo.getEndTime()));
        }
        //根据条件查询股票所有日数据
        List<Stock> list = baseMapper.selectList(wrapper);
        //对所有日数据进行封装，方便前端渲染
        List<BigDecimal> open = list.stream().map(Stock::getOpen).collect(Collectors.toList());
        List<BigDecimal> close = list.stream().map(Stock::getClose).collect(Collectors.toList());
        List<BigDecimal> high = list.stream().map(Stock::getHigh).collect(Collectors.toList());
        List<BigDecimal> low = list.stream().map(Stock::getLow).collect(Collectors.toList());
        //日期类型暂时转换成字符串方便前端渲染
        List<String> date = list.stream().map(x -> {
            return new SimpleDateFormat("yyyy-MM-dd").format(x.getDate());
        }).collect(Collectors.toList());
//        List<Date> date = list.stream().map(Stock::getDate).collect(Collectors.toList());
        List<Long> volume = list.stream().map(Stock::getVolume).collect(Collectors.toList());

        map.put("list",list);
        map.put("open",open);
        map.put("close",close);
        map.put("high",high);
        map.put("low",low);
        map.put("date",date);
        map.put("volume",volume);
        return map;
    }

    //从mongodb中获取预测数据和真实数据
    @Override
    @Cacheable(value = "mongo",keyGenerator = "keyGenerator")
    public StockMongo findMongo(String label) {
        log.info("从mongodb中获取");
        if(!StringUtils.isEmpty(label)){
            Query query = Query.query(Criteria.where("label").is(label));
            return  mongoTemplate.findOne(query, StockMongo.class);
        }else{
            Query query = Query.query(Criteria.where("label").is("SimpleRNN"));
            return  mongoTemplate.findOne(query, StockMongo.class);
        }
    }
}
